package com.lin.thread;


import com.lin.utils.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 异步任务管理器
 */
public class AsyncManager {

    private static final Logger logger = LoggerFactory.getLogger(AsyncManager.class);

    /**
     * 操作延迟10毫秒
     */
    private final int OPERATE_DELAY_TIME = 0;

    /**
     * 异步操作任务调度线程池
     */
    private ScheduledExecutorService poolTaskExecutor = SpringUtils.getBean("scheduledExecutorService");


    private static ThreadPoolExecutor executor = SpringUtils.getBean("threadPoolExecutor");


    /**
     * 单例模式
     */
    private AsyncManager() {
    }

    private static AsyncManager me = new AsyncManager();

    public static AsyncManager me() {
        return me;
    }

    /**
     * 执行任务
     *
     * @param task 任务
     */
    public void execute(Runnable task) {

        executor.execute(task);
    }

    public void execute2(TimerTask task)
    {
        poolTaskExecutor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }

    /**
     * 停止线程池
     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
     * 如果仍然超時，則強制退出.
     * 另对在shutdown时线程本身被调用中断做了处理.
     */
    public void shutdown() {

        if (executor != null && !executor.isShutdown()) {
            // 会将线程池状态置为SHUTDOWN，不再接受新的任务，同时会等待线程池中已有的任务执行完成再结束。
            executor.shutdown();
            try {
                if (!executor.awaitTermination(120, TimeUnit.SECONDS)) {
                    // 尝试停止所有正在执行的任务，停止等待任务的处理，并返回等待执行任务的列表。
                    executor.shutdownNow();
                    if (!executor.awaitTermination(120, TimeUnit.SECONDS)) {
                        logger.info("Pool did not terminate");
                    }
                }
            } catch (InterruptedException ie) {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }

    }

    /**
     * 等待线程池任务完成，此方法一般用于判断线程池中的任务是否执行完毕
     * @return 如果过了时间，且线程池中的线程都执行完毕，返回true。如果过了时间，且线程池中的线程没有执行完毕，返回false
     * @throws InterruptedException
     */
    public boolean await() throws InterruptedException {
        // awaitTermination 此方法会使主线程处于阻塞状态
        return executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); // 等待所有任务完成
    }
}
